package group.sicher.core.utils;

import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class DataTransformUtils {
    private static final Logger logger = LoggerFactory.getLogger(DataTransformUtils.class);

    /**
     * 拷贝 source 属性值 到 target 对应的属性值
     *
     * @param source
     * @param target
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> T copy(K source, T target) {
        return copyObjFields(source, target, false, false);
    }

    /**
     * 拷贝 source 属性值 到 target 对应的属性值
     * 忽略属性： 空指针、空字符串
     *
     * @param source
     * @param target
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> T copyIgnoreNullAndStrBlank(K source, T target) {
        return copyObjFields(source, target, true, true);
    }

    /**
     * 拷贝 source 属性值 到 target 对应的属性值
     * 忽略属性： 空指针
     *
     * @param source
     * @param target
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> T copyIgnoreNull(K source, T target) {
        return copyObjFields(source, target, true, false);
    }

    /**
     * 拷贝 source 属性值 到 target 对应的属性值
     * 忽略属性： 字符串空指针、空字符串
     *
     * @param source
     * @param target
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> T copyIgnoreStrBlank(K source, T target) {
        return copyObjFields(source, target, false, true);
    }

    /**
     * 拷贝 source 属性值 到 target 对应的属性值
     *
     * @param source            源对象
     * @param target            目标对象
     * @param ignoreNull        忽略 空属性
     * @param ignoreStringBlank 忽略 空字符串
     * @param <T>
     * @param <K>
     * @return
     */
    private static <K, T> T copyObjFields(K source, T target, boolean ignoreNull, boolean ignoreStringBlank) {
        if (null == source) {
            return target;
        }
        try {
            Map<String, Field> sFieldMap = getDeclareFieldsMap(source);
            Field[] fields = target.getClass().getDeclaredFields();
            for (Field tField : fields) {
                Field sField = sFieldMap.get(tField.getName());
                if (null != sField && tField.getType().getName().equals(sField.getType().getName())) {
                    tField.setAccessible(true);
                    sField.setAccessible(true);
                    if (ignoreNull) {
                        if (null == sField.get(source)) {
                            continue;
                        }
                    }
                    if (ignoreStringBlank) {
                        if (String.class.getName().equals(sField.getType().getName())
                                && StringUtils.isBlank((String) sField.get(source))) {
                            continue;
                        }
                    }
                    tField.set(target, sField.get(source));
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return target;
    }

    /**
     * 获取目标对象的属性hash集合
     *
     * @param obj
     * @return
     */
    private static Map<String, Field> getDeclareFieldsMap(Object obj) {
        Map<String, Field> fieldMap = new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            fieldMap.put(field.getName(), field);
        }
        return fieldMap;
    }

    /**
     * A类型 转 B类型的list集合
     *
     * @param res
     * @param clazz
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> List<T> transformList(List<K> res, Class<T> clazz) {
        if (CollectionUtils.isEmpty(res)) {
            return Lists.newArrayList();
        }
        List<T> list = Lists.newArrayList();
        res.stream().forEach(tmp -> {
            try {
                T out = clazz.newInstance();
                BeanUtils.copyProperties(tmp, out);
                list.add(out);
            } catch (InstantiationException e) {
                logger.error(e.getMessage(), e);
            } catch (IllegalAccessException e) {
                logger.error(e.getMessage(), e);
            }
        });
        return list;
    }

    /**
     * A类型转B类型 实体
     *
     * @param res
     * @param clazz
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> T transformEntity(K res, Class<T> clazz) {
        if (null == res) {
            return null;
        }
        T outRes = null;
        try {
            outRes = clazz.newInstance();
            BeanUtils.copyProperties(res, outRes);
        } catch (InstantiationException e) {
            logger.error(e.getMessage(), e);
        } catch (IllegalAccessException e) {
            logger.error(e.getMessage(), e);
        }
        return outRes;
    }

}
